#ifndef THREADPOOL_H
#define THREADPOOL_H

#include<mutex>
#include<condition_variable>
#include<queue>
#include<thread>
#include<functional>
#include<assert.h>

class ThreadPool {
public:
    ThreadPool() = default;
    ThreadPool(ThreadPool&&) = default;
    explicit ThreadPool(size_t threadCount = 8) : pool_{std::make_shared<Pool>()} {
        assert(threadCount > 0);
        for(size_t i = 0; i < threadCount; i++) {
            //创建一个线程
            std::thread([this]() {
                std::unique_lock<std::mutex> locker(pool_->mtx);
                while(true) {
                    if(!pool_->tasks.empty()) {  //非空，当前有任务需要执行
                        auto task = std::move(pool_->tasks.front());
                        pool_->tasks.pop();   //
                        locker.unlock();        //解锁, 因为任务已经取出
                        task();         //执行该函数
                        locker.lock();   //加锁防止其再次执行
                    }
                    else if(pool_->isClosed) break;  //初步执行到这里跳出
                    else pool_->cond.wait(locker);  //阻塞等待任务
                }
            }).detach();    //交与后台自动执行，线程结束时资源自动释放
        }
    }

    ~ThreadPool() {
        if(static_cast<bool>(pool_)) {
            std::lock_guard<std::mutex> locker(pool_->mtx);
            pool_->isClosed = true;
        }
        pool_->cond.notify_all();
    }

    template<class F>
    void AddTask(F&& task) {
        std::lock_guard<std::mutex> locker(pool_->mtx);
        pool_->tasks.emplace(std::forward<F>(task));   //加入任务队列
        
        pool_->cond.notify_one();   //唤醒一个工作线程
    }

private:
    struct Pool {
        std::mutex mtx;
        std::condition_variable cond;
        bool isClosed;
        std::queue<std::function<void()>> tasks;  //保存无返回值无参数的函数队列
    };
    std::shared_ptr<Pool> pool_;
};

#endif